﻿using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;

public enum WeaponType
{
    Archer=0,
    Light=1,
    Heavy=2
}

public class PlayerController2D : Character,IDamage
{
    private Rigidbody2D rb;
    private BoxCollider2D boxColider;
    public float speed =1;
    public float leaderSpeed = 0.5f;
    private float xInput;
    [Header("冲刺")]
    public AnimationCurve dushCurve;
    public float dushSpeed = 3;
    [Header("跳跃")]
    public bool isGround = true;
    public float Jumpheight = 0.2f;
    public LayerMask Ground;
    public int JumpCount = 2;
    float indexJump = 0;
    public bool isjump = false;

    public bool isInvincible = false; //无敌
    private float invincibletimer;
    //平台检测
    public Collision2D contactObj;
    private const string Contacttag = "Contact";
    [Header("Attack")]
    private float timer;
    private bool isAttack;
    public float interval = 2;
    private int attackCount = 0;
    [Header("补偿速度")]
    public float archerAttackSpeed;
    public float lightAttackSpeed;
    public float heavyAttackSpeed;
    private bool isLeader = false;

    public override void Awake()
    {
        base.Awake();
        DontDestroyOnLoad(gameObject);
        rb = GetComponent<Rigidbody2D>();
        boxColider = GetComponent<BoxCollider2D>();
    }
    
    private void Update()
    {
        if (isDeath)
        {
            return;
        }
        SetMotionStateInfo();
        CheeckSwitchWeapon();
        CheckInvincible();
    }

    public void CheeckSwitchWeapon()
    {
        if (InputManager.GetKeyDown("SelectWeapon"))
        {
            int index = (int)characterInfo.weaponType;
            index++;
            index %= 3;
            SetWeapon((WeaponType)index);
        }
    }
    public void SetWeapon(WeaponType weaponType)
    {
        this.characterInfo.weaponType = weaponType;
        animator.SetInteger("Weapon",(int)characterInfo.weaponType);
    }

    #region motion
    private void SetMotionStateInfo()
    {
        isjump |= InputManager.GetKeyDown("Jump");
        bool left = InputManager.GetKeyDown("Left");
        bool right = InputManager.GetKeyDown("Right");

        if (left && right)
        {
            xInput = 0;
        }
        else if (left)
        {
            spriteRenderer.flipX = true;
            xInput = -1;
        }
        else if (right)
        {
            spriteRenderer.flipX = false;
            xInput = 1;

        }
        else
        {
            xInput = 0;
        }
        if (isGround)
        {

            Attack();
             if (InputManager.GetKeyDown("Rush"))
            {
                ToDush();
            }
        }
        Move();


    }

    public void Move()
    {
        if (isLeader)
        {
            if (InputManager.GetKeyDown("Up"))
            {
                rb.velocity = new Vector2(xInput * characterInfo.moveSpeed, leaderSpeed);
            }
            else if (InputManager.GetKeyDown("Down"))
            {
                rb.velocity = new Vector2(xInput * characterInfo.moveSpeed, -leaderSpeed);
            }
            return;
        }
        else if (isAttack)
        {
            switch (characterInfo.weaponType)
            {
                case WeaponType.Archer:
                    rb.velocity = new Vector2(-forward * archerAttackSpeed, rb.velocity.y);
                    break;
                case WeaponType.Light:
                    rb.velocity = new Vector2(forward * lightAttackSpeed, rb.velocity.y);
                    break;
                case WeaponType.Heavy:
                    rb.velocity = new Vector2(forward * heavyAttackSpeed, rb.velocity.y);
                    break;
            }
           
        }
        else
        {
            rb.velocity = new Vector2(xInput * characterInfo.moveSpeed, rb.velocity.y);
        }
        speedVal.x = Mathf.Abs(rb.velocity.x);
        speedVal.y = Mathf.Abs(rb.velocity.y);
        animator.SetFloat("Speed", speedVal.x);
    }
    public void FixedUpdate()
    {
        if (isDeath)
        {
            return;
        }
        isGround = CheckIsGround();
        animator.SetBool("IsGround",isGround);
        CheckJump();
       
    }

    IEnumerator EnableBoxColider(BoxCollider2D box,float time)
    {
        yield return new WaitForSeconds(time);
        box.enabled = true;
    }
    public virtual void CheckJump()
    {
        if (isjump)
        {
            isjump = false;
            if (isGround)
            {
                indexJump = 0;
            }
            if (indexJump > JumpCount-1)
            {
                return;
            }
            if (InputManager.GetKeyDown("Down"))  //跳下平台
            {
                if (contactObj != null)
                {
                    if (contactObj.gameObject.GetComponent<PlatformEffector2D>())
                    {
                        BoxCollider2D collider2D = contactObj.gameObject.GetComponent<BoxCollider2D>();
                        collider2D.enabled = false ;
                        StartCoroutine(EnableBoxColider(collider2D,0.3f));
                    }
                }
            }
            else
            {
                rb.velocity = new Vector2(xInput * characterInfo.moveSpeed, Mathf.Sqrt(-2 * Physics.gravity.y * Jumpheight));
                if (indexJump == 0)
                {
                    animator.SetTrigger("Jump");
                }
                else
                {
                    animator.Play("Jump", 0, 0); ;
                }

                indexJump++;
            }


        }
    }
    private bool CheckIsGround()
    {
        float halfSize = boxColider.size.x * 0.5f;
        if (Physics2D.Raycast(transform.position+new Vector3(halfSize,0,0),Vector3.down,0.02f,Ground)|| Physics2D.Raycast(transform.position + new Vector3(-halfSize, 0, 0), Vector3.down, 0.02f, Ground))
        {

            return true;
        }
        return false;
    }



    #endregion

    #region Attack


    void Attack()
    {
        if (InputManager.GetKeyDown("Attack")&&!isAttack)
        {
            isAttack = true;
            if (attackCount>2)
            {
                attackCount = 0;
            }
            timer = interval;
            animator.SetTrigger("Attack");
            animator.SetInteger("AttackCount",attackCount);
            attackCount++;
        }
        if (timer!=0)
        {
            timer -= Time.deltaTime;
            if (timer<=0)
            {
                timer = 0;
                attackCount = 0;
                
            }
           
        }
    }
    public void EndAttack()
    {
        isAttack = false;
    }
    


    #endregion

    #region Dush
    public void ToDush()
    {
        animator.SetTrigger("Rush");

    }
    /// <summary>
    /// 冲刺
    /// </summary>
    /// <param name="time"></param>
    public override void Dush(float time)
    {
        StartCoroutine(DushInvoke(time));
        
    }
    private IEnumerator DushInvoke(float time)
    {
        float t = 0;
        isInvincible = true;
        while (t<time)
        {
            rb.velocity = new Vector2(forward * dushCurve.Evaluate(t / time) * dushSpeed, rb.velocity.y);
            t += Time.deltaTime;
            yield return null;
        }
        isInvincible = false;
    }
    #endregion
    public void OnCollisionStay2D(Collision2D collision)
    {
        if (collision.gameObject.tag== Contacttag)
        {
            contactObj = collision;
        }

    }
    /// <summary>
    /// 击退
    /// </summary>
    /// <param name="time"></param>
    /// <param name="dir"></param>
    /// <returns></returns>
    private IEnumerator Repel(float time,int dir)
    {
        float t = 0;
        SetisInvincibleTime(time);
        while (t<time)
        {
            t += Time.deltaTime;
            rb.velocity = new Vector2(dir*0.7f,rb.velocity.y);
            yield return null;
        }
    }
    /// <summary>
    /// 受伤
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="pos"></param>
    /// <param name="attack"></param>
    public void OnDamage(GameObject sender, Vector3 pos,int attack)
    {
        isAttack = false;
        if (isInvincible)
            return;
        characterInfo.TakeHp(attack);
        if (characterInfo.hp<=0)
        {
            isDeath = true;
            if (onDeath!=null)
            {
                onDeath();
            }
            GameManager.Instance.GameOver();
            Invoke("ReStartPlayer", 2);
            return;
        }
        Vector2 vec = pos - transform.position;
        float dot= Vector3.Dot(transform.position+new Vector3(forward,0,0),vec);
        if (dot>0) //正向
        {
            animator.SetTrigger("HitForward");
            StartCoroutine(Repel(0.5f,-1));
        }
        else
        {
            animator.SetTrigger("HitBack");
            StartCoroutine(Repel(0.4f, 1));
        }
        SetisInvincibleTime(0.5f);
        
    }
    bool sceneIsLoading=false;
    /// <summary>
    /// 重置Player
    /// </summary>
    public void ReStartPlayer()
    {
        if (SceneManager.GetActiveScene().name!="Level1")
        {
            if (!sceneIsLoading)
            {
                GameManager.Instance.AsyncLoadScene("Level1", () => {
                    transform.position = DefaultData.playerDefultPos;
                    characterInfo.RestoreHp(characterInfo.maxHp);
                    isDeath = false;
                    sceneIsLoading = false;
                });
            }
            sceneIsLoading = true;
        }
        else
        {
            transform.position = DefaultData.playerDefultPos;
            characterInfo.RestoreHp(characterInfo.maxHp);
            isDeath = false;
        }
        

    }

    public void SetLeader(bool v)
    {
        isLeader = v;

    }

    public void SetisInvincibleTime(float time)
    {
        if (time<=0)
        {
            return;
        }
        invincibletimer = time;
        isInvincible = true;
    }
    private void CheckInvincible()
    {
        if (invincibletimer > 0)
        {
            invincibletimer -= Time.deltaTime;
            if (invincibletimer<=0)
            {
                invincibletimer = 0;
                isInvincible = false;
            }
        }
    }

}

